/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.nct.cachedclient;

import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import net.spy.memcached.AddrUtil;
import net.spy.memcached.MemcachedClient;
import net.spy.memcached.internal.OperationFuture;
import org.apache.log4j.Logger;
import org.nct.StaticVariable.StaticVariable;
import org.nct.logger.MyLogger;

/**
 *
 * @author annn
 */
public class CachedClient {

    public MemcachedClient memCachedClient = null;

    int IDClient = 0;

    public CachedClient(int _IDClient) {
        IDClient = _IDClient;
        try {
            memCachedClient = new MemcachedClient(AddrUtil.getAddresses(StaticVariable.hosts));
            MyLogger.getInstance().Info("Client " + IDClient + ": Connect Success To Server...." + StaticVariable.hosts);
        } catch (IOException ex) {
            MyLogger.getInstance().Error(ex.getMessage());
        }
    }

    public synchronized Object getValue(String key) {
        Object obj = memCachedClient.get(key);
        System.out.println(obj);
        if (obj != null) {
            MyLogger.getInstance().Info("Client " + IDClient + ": Get value with key = " + key);
        } else {
            MyLogger.getInstance().Error("Client " + IDClient + ": Get value = 'NULL' with key = " + key);
        }
        return obj;
    }

    public synchronized Object getValue(String key, boolean async) {
        if (async) {
            Object myObj = null;
            Future<Object> f = memCachedClient.asyncGet(key);

            try {
                myObj = f.get(5, TimeUnit.SECONDS);
                MyLogger.getInstance().Info("Client " + IDClient + ": Get value with key = " + key);
            } catch (InterruptedException | ExecutionException | TimeoutException ex) {
                f.cancel(false);
                MyLogger.getInstance().Error("Client " + IDClient + ": " + ex.getMessage());
            }

            return myObj;
        } else {
            return getValue(key);
        }
    }

    public synchronized boolean setValue(String key, Object value) {
        boolean flag = false;
        OperationFuture<Boolean> f = memCachedClient.set(key, StaticVariable.expires, value);
        try {
            flag = f.get(5, TimeUnit.SECONDS);
            MyLogger.getInstance().Info("Client " + IDClient + ": Set [" + key + ", " + value + "] Success");

        } catch (InterruptedException | TimeoutException | ExecutionException ex) {
            f.cancel(true);
            MyLogger.getInstance().Info("Client " + IDClient + ": Not Set [" + key + ", " + value + "] Success");
        }
        return flag;
    }

    public synchronized boolean setValue(String key, Object value, boolean async) {
        if (async) {
            OperationFuture<Boolean> f = memCachedClient.set(key, StaticVariable.expires, value);
            try {
                f.get(5, TimeUnit.SECONDS);
                MyLogger.getInstance().Info("Client " + IDClient + ": Set [" + key + ", " + value + "] Success");
                return true;
            } catch (InterruptedException | ExecutionException | TimeoutException ex) {
                f.cancel(false);
                MyLogger.getInstance().Info("Client " + IDClient + ": Not Set [" + key + ", " + value + "] Success");
            }
            return false;
        } else {
            return setValue(key, value);
        }
    }

    public synchronized boolean deteleKey(String key) {
        boolean flag = false;
        OperationFuture<Boolean> f = memCachedClient.delete(key);

        try {
            flag = f.get(5, TimeUnit.SECONDS);
            MyLogger.getInstance().Info("Client " + IDClient + ": Delete [" + key + "] Success");

        } catch (InterruptedException | TimeoutException | ExecutionException ex) {
            f.cancel(true);
            MyLogger.getInstance().Info("Client " + IDClient + ": Not Delete [" + key + "] Success");
        }
        return flag;

    }

    public synchronized boolean deteleKey(String key, boolean async) {
        if (async) {
            OperationFuture<Boolean> f = memCachedClient.delete(key);
            try {
                f.get(5, TimeUnit.SECONDS);
                MyLogger.getInstance().Info("Client " + IDClient + ": Delete [" + key + "] Success");
                return true;
            } catch (InterruptedException | ExecutionException | TimeoutException ex) {
                f.cancel(false);
                MyLogger.getInstance().Info("Client " + IDClient + ": Not Delete [" + key + "] Success");
            }
            return false;
        } else {
            return deteleKey(key);
        }
    }

}
